import Designer from '@/index';
import { nodesToMap } from './node';

/**
 * 键盘热键判断
 * @param {KeyboardEvent} e
 * @param {string[]} keys https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values
 */
export const hotkey = (e, keys, prevent = true) => {
  if (!keys || !keys.length) return false;
  const { key, ctrlKey, shiftKey, altKey, metaKey } = e;
  if (keys.pop().toLocaleLowerCase() !== key.toLocaleLowerCase()) return false;
  // ctrl键等价meta键，兼容Mac系统
  if ((ctrlKey || metaKey) !== keys.includes('ctrl')) return false;
  if (shiftKey !== keys.includes('shift')) return false;
  if (altKey !== keys.includes('alt')) return false;
  if (prevent) e.preventDefault();
  return true;
};

// 合并节点数据时需要忽略的属性
const ignoreKeys = { className: 1, parent: 1, nodes: 1 };
/**
 * 节点数据合并
 * @param {*} node 目标节点数据
 * @param {*} newNode 新的节点数据
 * @returns
 */
export const nodeMerge = (node, newNode) => {
  const nodes = node.nodes;
  const newNodes = newNode.nodes;
  // 合并子节点数据
  if (Array.isArray(nodes) && Array.isArray(newNodes)) nodesMerge(node, nodes, newNodes);
  // 忽略画布节点
  if (node.className === 'Stage') return node;
  // 合并节点数据
  Object.keys(newNode).forEach((key) => {
    if (ignoreKeys[key]) return;
    if (node[key] === newNode[key]) return;
    node[key] = newNode[key];
    // 图片资源地址变更，更新图片
    if (key === 'src') node.setImage?.(newNode[key]);
    if (key === 'icon') node.setIcon?.(newNode[key]);
  });
  return node;
};

/**
 * 子节点数据合并
 * @param {*} parent 父级节点
 * @param {*} nodes 目标子节点数据
 * @param {*} newNodes 新子节点数据
 * @returns
 */
export const nodesMerge = (parent, nodes, newNodes) => {
  // 将目标子节点数组转换为节点映射对象
  const nodesMap = nodesToMap(nodes);
  // 将新子节点数组转换为节点映射对象
  const newNodesMap = nodesToMap(newNodes);
  // 反向遍历当前子节点数据
  for (let i = nodes.length - 1; i >= 0; i--) {
    const node = nodes[i];
    // 寻找相同 id 的新节点
    const newNode = newNodesMap[node.id];
    // 不存在相同 id 的新节点，删除当前节点
    if (!newNode) nodes.splice(i, 1);
    // 存在相同 id 的新节点，合并节点数据
    else nodeMerge(node, newNode);
  }
  // 遍历新的子节点数据
  for (const newNode of newNodes) {
    // 寻找相同 id 的节点
    const node = nodesMap[newNode.id];
    // 不存在相同 id 的节点，实例化新节点并添加到父级节点
    if (!node) Designer.create(newNode, { parent });
  }
  // 按照深度属性排序所有节点
  nodes.sort((a, b) => a.zIndex - b.zIndex);
};
